// 引入axios用于发起HTTP请求，引入ElMessage用于在页面上显示消息提示
import axios from "axios";
import {ElMessage} from "element-plus";

// 用于存储授权信息的本地存储或会话存储的键名
const authItemName = "authorize"
// 获取带有授权令牌的请求头
const accessHeader = () => {
    const token = takeAccessToken();
    // 如果存在令牌，返回带有Bearer令牌的请求头；否则返回空对象
    return token? {
        'Authorization': `Bearer ${takeAccessToken()}`
    }:{}
}
// 默认的请求失败处理函数
const defaultFailure = (message, status, url) => {
    // 在控制台打印请求失败的警告信息，包括请求地址、状态码和错误信息
    console.warn(`请求地址: ${url}, 状态码: ${status}, 错误信息: ${message}`)
    // 在页面上显示警告消息
    ElMessage.warning(message)
}
// 默认的请求错误处理函数
const defaultError = (error) => {
    // 在控制台打印错误信息
    console.error(error)
    // 在页面上显示错误消息，提示用户联系管理员
    ElMessage.error('发生了一些错误，请联系管理员')
}
// 存储访问令牌到本地存储或会话存储
function storeAccessToken(remember, token, expire){
    // 构建包含令牌和过期时间的授权对象
    const authObj = {
        token: token,
        expire: expire
    }
    // 将授权对象转换为JSON字符串
    const str = JSON.stringify(authObj)
    // 根据remember标志决定存储到本地存储还是会话存储
    if(remember)
        localStorage.setItem(authItemName, str)
    else
        sessionStorage.setItem(authItemName, str)
}

// 获取访问令牌
function takeAccessToken() {
    // 尝试从本地存储或会话存储中获取授权信息字符串
    const str = localStorage.getItem(authItemName) || sessionStorage.getItem(authItemName);
    // 如果未获取到，返回null
    if(!str) return null
    // 将获取到的JSON字符串转换为对象
    const authObj = JSON.parse(str)
    // 如果令牌已过期，删除存储的授权信息，显示警告消息，并返回null
    if(authObj.expire <= new Date()) {
        deleteAccessToken()
        ElMessage.warning("登录状态已过期，请重新登录！")
        return null
    }
    // 返回有效的访问令牌
    return authObj.token
}

// 删除存储的访问令牌
function deleteAccessToken() {
    // 从本地存储和会话存储中移除授权信息
    localStorage.removeItem(authItemName)
    sessionStorage.removeItem(authItemName)
}
// 内部POST请求函数
function internalPost(url, data, headers, success, failure, error = defaultError){
    // 发起POST请求，传入请求地址、数据和请求头
    axios.post(url, data, { headers: headers }).then(({data}) => {
        // 如果响应数据的code为200，调用成功回调函数并传入响应数据
        if(data.code === 200)
            success(data.data)
        // 否则，调用失败回调函数并传入错误消息、状态码和请求地址
        else
            failure(data.message, data.code, url)
    }).catch(err => error(err))
}

// 内部GET请求函数
function internalGet(url, headers, success, failure, error = defaultError){
    // 发起GET请求，传入请求地址和请求头
    axios.get(url, { headers: headers }).then(({data}) => {
        // 如果响应数据的code为200，调用成功回调函数并传入响应数据
        if(data.code === 200)
            success(data.data)
        // 否则，调用失败回调函数并传入错误消息、状态码和请求地址
        else
            failure(data.message, data.code, url)
    }).catch(err => error(err))
}

// 登录函数
function login(username, password, remember, success, failure = defaultFailure){
    // 发起登录的POST请求
    internalPost('/api/auth/login', {
        username: username,
        password: password
    }, {
        'Content-Type': 'application/x-www-form-urlencoded'
    }, (data) => {
        // 存储登录成功返回的令牌和过期时间
        storeAccessToken(remember, data.token, data.expire)
        // 显示登录成功的提示消息
        ElMessage.success(`登录成功，欢迎 ${data.username} 来到我们的系统`)
        // 调用成功回调函数并传入响应数据
        success(data)
    }, failure)
}
// 登出函数
function logout(success, failure = defaultFailure){
    // 发起登出的GET请求
    get('/api/auth/logout', () => {
        // 删除存储的访问令牌
        deleteAccessToken()
        // 显示登出成功的提示消息
        ElMessage.success(`退出登录成功，欢迎您再次使用`)
        // 调用成功回调函数
        success()
    }, failure)
}
// 发起GET请求的对外接口函数
function get(url, success, failure = defaultFailure) {
    // 调用内部GET请求函数，传入带有授权头的请求头
    internalGet(url, accessHeader(), success, failure)
}
// 发起POST请求的对外接口函数
function post(url, data, success, failure = defaultFailure) {
    // 调用内部POST请求函数，传入带有授权头的请求头
    internalPost(url, data, accessHeader() , success, failure)
}
// 判断用户是否未授权
function unauthorized() {
    // 如果获取不到访问令牌，返回true，否则返回false
    return !takeAccessToken()
}
// 对外导出登录、登出、GET请求、POST请求和判断未授权状态的函数
export {login,logout,get,post,unauthorized,accessHeader}